package com.isatechindonesia.isatracker.service;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.List;
import java.util.Locale;

import com.isatechindonesia.isatracker.DBClass;
import com.isatechindonesia.isatracker.Logger;

import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class GPSLoggerService extends Service {	

	private LocationManager lm;
	private LocationListener locationListener;
	
	private static String idgps;
	private static long minTimeMillis;
	private static long minDistanceMeters;
	private static float minAccuracyMeters;
	
	private int lastStatus = 0;
	private static boolean showingDebugToast = false;
	
	private static final String tag = "GPSLoggerService";

	/** Called when the activity is first created. */
	private void startLoggerService() {

		SharedPreferences pref = getApplicationContext().getSharedPreferences("gpsconfig", MODE_PRIVATE);
		
		idgps = pref.getString("idgps", "0000");	
		minTimeMillis = Long.valueOf(pref.getString("idtime", "1000"));
		minDistanceMeters = Long.valueOf(pref.getString("iddist", "10"));
		minAccuracyMeters = Long.valueOf(pref.getString("idacc", "35"));
		
		Log.i("idgps--->", "" + idgps);
		Log.i("Accuracy--->", "" + minAccuracyMeters);
		
		// ---use the LocationManager class to obtain GPS locations---
		lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		locationListener = new MyLocationListener();						
		
		lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 
				minTimeMillis, 
				minDistanceMeters,
				locationListener);										
		
	}

	private void shutdownLoggerService() {
		lm.removeUpdates(locationListener);
	}
	
	public class MyLocationListener implements LocationListener {
		
		@Override
		public void onLocationChanged(final Location loc) {
			if (loc != null && !idgps.equalsIgnoreCase("0000")) {
				try {			
					
					if (loc.hasAccuracy() && loc.getAccuracy() <= minAccuracyMeters) {
						
						/*
						Thread splashTread = new Thread() {
							@Override
							public void run() {
								try {
									synchronized (this) {
										wait(500);
									}

								} catch (InterruptedException e) {
								} finally {
									
									startLocationUpdates(loc);		
									
								}
							}
						};

						splashTread.start();										
						*/
						
						startUpdateLogger(loc);
						
					} 
				} catch (Exception e) {
					Log.e(tag, e.toString());
				} 				
			}
		}

		@Override
		public void onProviderDisabled(String provider) {
			if (showingDebugToast) Toast.makeText(getBaseContext(), "onProviderDisabled: " + provider,
					Toast.LENGTH_SHORT).show();

		}

		@Override
		public void onProviderEnabled(String provider) {
			if (showingDebugToast) Toast.makeText(getBaseContext(), "onProviderEnabled: " + provider,
					Toast.LENGTH_SHORT).show();

		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			String showStatus = null;
			if (status == LocationProvider.AVAILABLE)
				showStatus = "Available";
			if (status == LocationProvider.TEMPORARILY_UNAVAILABLE)
				showStatus = "Temporarily Unavailable";
			if (status == LocationProvider.OUT_OF_SERVICE)
				showStatus = "Out of Service";
			if (status != lastStatus && showingDebugToast) {
				Toast.makeText(getBaseContext(),
						"new status: " + showStatus,
						Toast.LENGTH_SHORT).show();
			}
			lastStatus = status;
		}

	}
	
	public void startUpdateLogger(Location loc){

		if (loc != null) {
			
			Log.i("LatLon--->", loc.getLatitude() + " ** " + loc.getLongitude());
			Log.i("Speed--->", "" + loc.getSpeed());
			Log.i("Heading--->", "" + loc.getBearing());
			
			Logger log = new Logger();
			log.setLat(loc.getLatitude());
			log.setLon(loc.getLongitude());
			log.setSpeed(loc.getSpeed());
			log.setHeading(loc.getBearing());
			log.setAltitude(loc.getAltitude());
			log.setAccuracy(loc.getAccuracy());
			
			DBClass db = new DBClass(this);
			db.insertLog(log);
			
		}						
		
		
		
	}

	public void startLocationUpdates(Location loc) {		
		
		double lat = 0;
		double lon = 0;
		float speed = 0;
		float heading = 0;
		String address = "";
		boolean connected = false;

		if (loc != null) {
			lat = loc.getLatitude();
			lon = loc.getLongitude();
			speed = loc.getSpeed();
			heading = loc.getBearing();
		}						
					
		Geocoder geocoder = new Geocoder(this, Locale.getDefault());

		try {
			List<Address> addresses = geocoder.getFromLocation(lat, lon, 1);

			Log.i("LatLon--->", lat + " ** " + lon);
			Log.i("Speed--->", "" + speed);

			if (addresses != null && addresses.size() > 0) {
				Address returnedAddress = addresses.get(0);
				String addr = "";
				for (int i = 0; i < returnedAddress.getMaxAddressLineIndex(); i++) {
					addr = addr + " " + returnedAddress.getAddressLine(i);
				}

				if (lat != 0 && lon != 0)
					address = addr.trim();
				else
					address = "";

				Log.i("Address--->", address);

			} else {
				Log.i("Address--->", "Not Found");
			}

			try {

				InetAddress serverAddr = InetAddress.getByName("202.149.91.13");
				Log.d("client--->", "C: Connecting...");
				Socket socket = new Socket(serverAddr, 1500);
				connected = true;
				if (connected) {
					try {
						Log.d("client--->", "C: Sending command.");
						PrintWriter out = new PrintWriter(
								new BufferedWriter(new OutputStreamWriter(
										socket.getOutputStream())), true);
						// WHERE YOU ISSUE THE COMMANDS
						out.println(idgps+"," + lat + "," + lon + "," + speed
								+ "," + address + "," + heading);
						Log.d("client--->", "C: Sent.");
					} catch (Exception e) {
						Log.e("client--->", "S: Error", e);
					}
				}
				socket.close();
				Log.d("client--->", "C: Closed.");
			} catch (Exception e) {
				Log.e("client--->", "C: Error", e);
				connected = false;
			}
			

		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

	@Override
	public void onCreate() {
		super.onCreate();		
		
		Log.i("Service--->", "Started");
		startLoggerService();			
		
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		
		Log.i("Service--->", "Stopped");
		shutdownLoggerService();
				
	}

	// This is the object that receives interactions from clients. See
	// RemoteService for a more complete example.
	private final IBinder mBinder = new LocalBinder();

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

	public static void setMinTimeMillis(long _minTimeMillis) {
		minTimeMillis = _minTimeMillis;
	}

	public static long getMinTimeMillis() {
		return minTimeMillis;
	}

	public static void setMinDistanceMeters(long _minDistanceMeters) {
		minDistanceMeters = _minDistanceMeters;
	}

	public static long getMinDistanceMeters() {
		return minDistanceMeters;
	}

	public static float getMinAccuracyMeters() {
		return minAccuracyMeters;
	}
	
	public static void setMinAccuracyMeters(float minAccuracyMeters) {
		GPSLoggerService.minAccuracyMeters = minAccuracyMeters;
	}

	public static void setShowingDebugToast(boolean showingDebugToast) {
		GPSLoggerService.showingDebugToast = showingDebugToast;
	}

	public static boolean isShowingDebugToast() {
		return showingDebugToast;
	}

	/**
	 * Class for clients to access. Because we know this service always runs in
	 * the same process as its clients, we don't need to deal with IPC.
	 */
	public class LocalBinder extends Binder {
		GPSLoggerService getService() {
			return GPSLoggerService.this;
		}
	}

}
